<?php


use Illuminate\Database\Capsule\Manager as DB;

class Dianpu_WithdrawController extends CommonController
{
    #[获取可提现的店铺列表]
    public function getdianpuAction()
    {
        if (!$this->isPost()){
            ret(0, '请求出错！');
        }
        $id = $this->get('id');
        if(!empty($id) && !is_numeric($id)){
            ret(0, '搜索关键词只能是数字');
        }
        $query = dianpuModel::query()->where('member_id', '<>', $this->user->id)->where('status', 1)->whereNull('deleted_at');
        if(is_numeric($id)){
            $query = $query->where(function ($whereQuery) use($id){
                $whereQuery->where('id', $id)
                           ->orWhere('member_id', $id)
                           ->orWhere('phone', 'like',"%{$id}%")
                           ->orWhereIn('member_id', memberModel::query()->where('phone', 'like', "%{$id}%")->pluck('id'));
            });
        }
        $dianpuList = $query->orderByDesc('created_at')->limit(10)->select(['id', 'member_id', 'company_name', 'company_representative_name'])->get()->makeHidden('status_name');
        $list = [];
        if($dianpuList){
            $list = $dianpuList->toArray();
        }
        ret(1, '获取成功', $list);
    }

    #[获取店铺提现规则]
    public function ruleAction()
    {
        json(['code' => 1, 'msg' => '店铺提现规则', 'data' => dianpuwithdrawModel::getWithdrawConfig()]);
    }

    #[申请店铺提现]
    public function applyAction()
    {
        if (!$this->isPost()){
            ret(0, '请求出错！');
        }
        $dianpu_id = $this->get('dianpu_id');
        $dianpu_manager = $this->get('dianpu_manager_id');
        $money = $this->get('money', 0);
        $bank_id = $this->get('bank_id');
        $paypwd = $this->get('paypwd', '');
        try {
            if (!$this->user->pay_password) {
                throw new Exception('请设置支付密码');
            }
            if (md5($paypwd) != $this->user->pay_password) {
                throw new Exception('支付密码错误');
            }
            if (!is_numeric($bank_id) || mb_strpos($bank_id, '.') !== false ||$bank_id <= 0){
                throw new Exception('非法帐户！');
            }
            $bank = memberbankModel::query()->where('id', $bank_id)->where('member_id', $this->user->id)->first();
            if(empty($bank)){
                throw new Exception('提现帐户不存在！');
            }
            $withdrawRule = configModel::query()->where('type', 20)->pluck('value', 'key')->toArray();
            if(empty($withdrawRule)){
                throw new Exception('店铺提现规则未设置');
            }
            if (!isset($withdrawRule['enable_dianpu_withdraw']) || $withdrawRule['enable_dianpu_withdraw'] != 1){
                throw new Exception('店铺提现未启用');
            }
            $withdrawRule['dianpu_withdraw_min'] = $withdrawRule['dianpu_withdraw_min']?? 0;
            $withdrawRule['dianpu_withdraw_max'] = $withdrawRule['dianpu_withdraw_max']?? 0;
            $withdrawRule['dianpu_withdraw_quota'] = $withdrawRule['dianpu_withdraw_quota']?? 0;
            if(!is_numeric($money) || bccomp($money, 0, 2) <= 0){
                throw new Exception('提现金额不正确');
            }
            if($withdrawRule['dianpu_withdraw_min'] && bccomp($money, $withdrawRule['dianpu_withdraw_min'], 2) < 0){
                throw new Exception("提现金额不能小于{$withdrawRule['dianpu_withdraw_min']}");
            }
            if($withdrawRule['dianpu_withdraw_max'] && bccomp($money, $withdrawRule['dianpu_withdraw_max'], 2) > 0){
                throw new Exception("提现金额不能大于{$withdrawRule['dianpu_withdraw_max']}");
            }
            if (bccomp($this->user->money, $money, 2) < 0){
                throw new Exception("帐户余额不足");
            }
            if($withdrawRule['dianpu_withdraw_quota']){
                $today_money = dianpuwithdrawModel::query()->where('member_id', $this->user->id)->whereDate('created_at', '>=', date('Y-m-d', time()))->sum('money');
                $surplus_quota = bcsub($withdrawRule['dianpu_withdraw_quota'], $today_money, 2);
                if(bccomp($surplus_quota, 0, 2) <= 0){
                    throw new Exception("今日提现已达上限{$withdrawRule['dianpu_withdraw_quota']}");
                }
                if(bccomp($today_money, $surplus_quota, 2) > 0){
                    throw new Exception("今日提现额度剩余{$surplus_quota}");
                }
            }
            $dianpu = dianpuModel::query()->where('id', $dianpu_id)->where('member_id', $dianpu_manager)->where('status', 1)->whereNull('deleted_at')->first();
            if (!$dianpu){
                throw new Exception('店铺不存在或店铺已停用');
            }
            $calcd_money = dianpuwithdrawModel::calcActualMoney($money);
            switch ($bank->type){
                case 'bank':
                    $withdrawInfo = [
                        "真实姓名"=>$bank->real_name,
                        "开户行"=>$bank->bank_name,
                        "省"=>$bank->province,
                        "市"=>$bank->city,
                        "支行名称"=>$bank->branch_name,
                        "银行卡号"=>$bank->card_no,
                    ];
                    break;
                case 'weixin':
                    $withdrawInfo = [
                        "微信用户"=>$bank->real_name,
                        "微信ID"=>$bank->card_no,
                    ];
                    break;
                case 'alipay':
                    $withdrawInfo = [
                        "真实姓名"=>$bank->real_name,
                        "支付宝账户"=>$bank->card_no,
                    ];
                    break;
                default:
                    $withdrawInfo = [];
            }
            $apply_data = [
                'member_id'=>$this->user->id,
                'dianpu_id'=>$dianpu->id,
                'dianpu_manager_id'=>$dianpu->member_id,
                'money'=>$calcd_money['money'],
                'actual_money'=>$calcd_money['actual_money'],
                'charge_money'=>$calcd_money['charge_money'],
                'service_fee'=>$calcd_money['service_fee'],
                'withdraw_type'=>$bank->type,
                'withdraw_info'=>json_encode($withdrawInfo, 256),
                'status'=>0,
                'paidoff_evidence_image'=>'',
                'remark'=>$this->get('remark','无'),
                'created_at'=>timestamp(),
                'updated_at'=>timestamp()
            ];
            $withdraw_log_data = [
                'event'=>'apply',
                'event_id'=>0,
                'remark'=>"{$this->user->nickname}申请向店铺{$dianpu->id}提现{$money}元",
                'oper_type'=>'user',
                'oper_id'=>$this->user->id,
                'created_at'=>timestamp(),
            ];
            $res = DB::transaction(function () use ($money, $apply_data, $withdraw_log_data) {
                //增加 店铺提现记录
                $withdraw_id = dianpuwithdrawModel::query()->insertGetId($apply_data);
                //变更会员的余额，并且写入余额变动日志
                memberModel::money(bcsub(0, $money, 2), $this->user->id, 'dianpuwithdrawapply', $withdraw_id, "申请向店铺{$apply_data['dianpu_id']}提现，扣除{$money}元");
                $withdraw_log_data['event_id'] = $withdraw_id;
                //写入 店铺提现log
                dianpuwithdrawlogModel::query()->insert($withdraw_log_data);
                //增加店铺的冻结金额
                dianpuModel::moneyWithdrawFreeze($money, $apply_data['dianpu_id'],'dianpuwithdrawapply');
                return $withdraw_id;
            });
            if($res){
                ret(1, '店铺提现申请成功，等待店铺掌柜处理！');
            }else{
                throw new Exception('申请店铺提现失败，请重新申请！');
            }
        }catch (Exception $e){
            ret(0, $e->getMessage());
        }
    }

    #[会员的店铺提现申请列表]
    public function userapplylistAction()
    {
        if (!$this->isPost()){
            ret(0, '请求出错');
        }
        $mode = $this->get('mode', 'waiting');
        $allMode = [
            'waiting'=>'待处理',
            'denied'=>'被拒绝',
            'agreed'=>'已同意',
            'confirming'=>'待确认',
            'finished'=>'已完成'
        ];
        if (!in_array($mode, array_keys($allMode))){
            ret(0, '请求模式出错');
        }
        $query = dianpuwithdrawModel::query()->with(['dianpu', 'dianpumanager'])->where('member_id', $this->user->id);
        switch ($mode){
            case 'finished':
                $query = $query->where('status', 3)->with(['dianpuwithdrawlogs' => function($withQuery){
                    $withQuery->where('event', 'paid');
                }]);
                break;
            case 'agreed':
                $query = $query->where('status', 1);
                break;
            case 'confirming':
                $query = $query->where('status', 2)->with(['dianpuwithdrawlogs' => function($withQuery){
                    $withQuery->where('event', 'paid');
                }]);
                break;
            case 'denied':
                $query = $query->where('status', -1);
                break;
            default:
                $query = $query->where('status', 0);
        }
        $total = $query->count('id');
        $query = $query->orderByDesc('created_at')->select(['id','member_id','dianpu_id','dianpu_manager_id','money', 'actual_money', 'charge_money','withdraw_type','withdraw_info','status','created_at']);
        $page = $this->get('page', 1);
        $limit = $this->get('rows', 10);
        $offset = ($page - 1) * $limit;
        $query = $query->offset($offset)->limit($limit);
        $rows = $query->get()->makeHidden(['withdraw_info']);
        json(['total' => $total, 'rows' => $rows]);
    }

    #[店铺的店铺提现申请列表]
    public function dianpuapplylistAction()
    {
        if (!$this->isPost()){
            ret(0, '请求出错');
        }
        $mode = $this->get('mode', 'paying');
        $allMode = [
            'paying'=>'待同意',
            'denied'=>'已拒绝',
            'agreed'=>'待打款',
            'paid'=>'已打款',
            'finished'=>'已完成'
        ];
        if (!in_array($mode, array_keys($allMode))){
            ret(0, '请求模式出错');
        }
        $dianpu_id = $this->get('id');
        if(is_numeric($dianpu_id)){
            $dianpu = dianpuModel::query()->find($dianpu_id);
            if (!$dianpu) {
                ret(0, '店铺不存在');
            }
            if ($dianpu->member_id !== $this->user->id) {
                ret(0, '你不是店铺掌柜');
            }
            if ($dianpu->status < 1) {
                ret(0, '店铺已停用');
            }
        }
        $query = dianpuwithdrawModel::query()->with(['member'])->where('dianpu_manager_id', $this->user->id);
        switch ($mode){
            case 'finished':
                $query = $query->where('status', 3);
                break;
            case 'paid':
                $query = $query->where('status', 2);
                break;
            case 'agreed':
                $query = $query->where('status', 1);
                break;
            case 'denied':
                $query = $query->where('status', -1);
                break;
            default:
                $query = $query->where('status', 0);
        }
        if($dianpu_id){
            $query = $query->where('dianpu_id', $dianpu_id);
        }
        $total = $query->count('id');
        $query = $query->orderByDesc('created_at')->select(['id','member_id','dianpu_id','money', 'actual_money', 'charge_money','withdraw_type','withdraw_info','status','created_at']);
        $page = $this->get('page', 1);
        $limit = $this->get('rows', 10);
        $offset = ($page - 1) * $limit;
        $query = $query->offset($offset)->limit($limit);
        $rows = $query->get()->makeHidden(['withdraw_info']);
        json(['total' => $total, 'rows' => $rows]);
    }

    #[申请详情API]
    public function infoAction()
    {
        if (!$this->isPost()){
            ret(0, '请求出错');
        }
        $id = $this->get('id');
        $mode = $this->get('mode', 'user');
        try {
            if($mode === 'dianpu'){
                $with = ['dianpu', 'member', 'dianpuwithdrawlogs'];
                $hidden = ['withdraw_info', 'status_name'];
            }else{
                $with = ['dianpu', 'dianpumanager', 'dianpuwithdrawlogs'];
                $hidden = ['withdraw_info', 'service_fee', 'status_name'];
            }
            $query = dianpuwithdrawModel::query()->with($with);
            if($mode === 'dianpu'){
                $query = $query->where('dianpu_manager_id', $this->user->id);
            }else{
                $query = $query->where('member_id', $this->user->id);
            }
            $info = $query->findOrFail($id)->makeHidden($hidden)->toArray();
            switch ($info['status']){
                case -1:
                    $info['status_name'] = ($mode === 'dianpu')?'已拒绝':'被拒绝';
                    break;
                case 1:
                    $info['status_name'] = ($mode === 'dianpu')?'已打款':'待确认';
                    break;
                case 2:
                    $info['status_name'] = ($mode === 'dianpu')?'已完成':'已完成';
                    break;
                default:
                    $info['status_name'] = ($mode === 'dianpu')?'待打款':'待处理';
            }
            ret(1, '获取成功', $info);
        }catch (Exception $e){
            ret(0, '店铺提现申请不存在');
        } finally {
            unset($id, $mode);
        }
    }

    #[用户取消提现申请]
    public function cancelAction()
    {
        if (!$this->isPost()){
            ret(0, '请求出错');
        }
        $id = $this->get('id');
        DB::beginTransaction();
        try {
            $apply = dianpuwithdrawModel::query()->where('member_id', $this->user->id)->where('id', $id)->lockForUpdate()->firstOrFail();
            if ($apply->status !== 0){
                throw new Exception('申请已被处理，无法取消', 30001);
            }
            $apply->status = -2;
            $apply->updated_at = timestamp();
            if($apply->save()){
                dianpuModel::moneyWithdrawFreeze($apply->money, $apply->dianpu_id, 'dianpuwithdrawcanceled');
                $withdraw_log_data = [
                    'event'=>'canceled',
                    'event_id'=>$apply->id,
                    'remark'=>"{$this->user->nickname}取消向店铺{$apply->dianpu_id}提现{$apply->money}元的申请",
                    'oper_type'=>'user',
                    'oper_id'=>$this->user->id,
                    'created_at'=>timestamp(),
                ];
                dianpuwithdrawlogModel::query()->insert($withdraw_log_data);
                memberModel::money($apply->money, $apply->member_id, 'dianpuwithdrawcanceled', $apply->id, "取消向店铺{$apply->dianpu_id}提现申请，退回{$apply->money}元");
                DB::commit();
                ret(1, '取消成功！');
            }else{
                throw new Exception('操作失败', 30001);
            }
        }catch (Exception $e){
            DB::rollback();
            ret(0, ($e->getCode() === 30001)?$e->getMessage():'店铺提现申请不存在');
        } finally {
            unset($id);
        }
    }

    #[店铺掌柜同意提现申请]
    public function agreeAction()
    {
        if (!$this->isPost()){
            ret(0, '请求出错');
        }
        $id = $this->get('id');
        DB::beginTransaction();
        try {
            $apply = dianpuwithdrawModel::query()->where('dianpu_manager_id', $this->user->id)->where('id', $id)->lockForUpdate()->firstOrFail();
            if ($apply->status !== 0){
                throw new Exception('申请已被处理，无法同意', 30001);
            }
            $apply->status = 1;
            $apply->updated_at = timestamp();
            if($apply->save()){
                $withdraw_log_data = [
                    'event'=>'agree',
                    'event_id'=>$apply->id,
                    'remark'=>"{$this->user->nickname}同意用户{$apply->member_id}的提现{$apply->money}元的申请",
                    'oper_type'=>'user',
                    'oper_id'=>$this->user->id,
                    'created_at'=>timestamp(),
                ];
                dianpuwithdrawlogModel::query()->insert($withdraw_log_data);
                DB::commit();
                ret(1, '操作成功，请去打款！');
            }else{
                throw new Exception('操作失败', 30001);
            }
        }catch (Exception $e){
            DB::rollback();
            ret(0, ($e->getCode() === 30001)?$e->getMessage():'店铺提现申请不存在');
        } finally {
            unset($id);
        }
    }

    #[店铺掌柜拒绝提现申请]
    public function deniedAction()
    {
        if (!$this->isPost()){
            ret(0, '请求出错');
        }
        $id = $this->get('id');
        DB::beginTransaction();
        try {
            $apply = dianpuwithdrawModel::query()->where('dianpu_manager_id', $this->user->id)->where('id', $id)->lockForUpdate()->firstOrFail();
            if ($apply->status !== 0){
                throw new Exception('申请已被处理，无法拒绝', 30001);
            }
            $apply->status = -1;
            $apply->updated_at = timestamp();
            if($apply->save()){
                dianpuModel::moneyWithdrawFreeze($apply->money, $apply->dianpu_id, 'dianpuwithdrawdenied');
                $withdraw_log_data = [
                    'event'=>'denied',
                    'event_id'=>$apply->id,
                    'remark'=>$this->get('remark', "{$this->user->nickname}拒绝用户{$apply->member_id}的提现{$apply->money}元的申请"),
                    'oper_type'=>'user',
                    'oper_id'=>$this->user->id,
                    'created_at'=>timestamp(),
                ];
                dianpuwithdrawlogModel::query()->insert($withdraw_log_data);
                memberModel::money($apply->money, $apply->member_id, 'dianpuwithdrawdenied', $apply->id, "掌柜{$apply->dianpu_manager_id}拒绝用户{$apply->member_id}的提现申请，退回{$apply->money}元");
                DB::commit();
                ret(1, '拒绝成功！');
            }else{
                throw new Exception('操作失败', 30001);
            }
        }catch (Exception $e){
            DB::rollback();
            ret(0, ($e->getCode() === 30001)?$e->getMessage():'店铺提现申请不存在');
        } finally {
            unset($id);
        }
    }

    #[店铺掌柜打款给申请人]
    public function paidAction()
    {
        if (!$this->isPost()){
            ret(0, '请求出错');
        }
        $id = $this->get('id');
        $paidoff_evidence_image = $this->get('evidence_image');
        DB::beginTransaction();
        try {
            if(!is_array($paidoff_evidence_image) || count($paidoff_evidence_image) === 0){
                throw new Exception('打款凭证未上传', 30001);
            }
            $apply = dianpuwithdrawModel::query()->where('dianpu_manager_id', $this->user->id)->where('id', $id)->lockForUpdate()->firstOrFail();
            if ($apply->status !== 1){
                throw new Exception('申请非同意状态，无法打款', 30001);
            }
            $apply->status = 2;
            $apply->updated_at = timestamp();
            $apply->paidoff_evidence_image = implode(',', $paidoff_evidence_image);
            if($apply->save()){
                $withdraw_log_data = [
                    'event'=>'paid',
                    'event_id'=>$apply->id,
                    'remark'=>"掌柜{$this->user->nickname}提交已打款证明",
                    'oper_type'=>'user',
                    'oper_id'=>$this->user->id,
                    'created_at'=>timestamp(),
                ];
                dianpuwithdrawlogModel::query()->insert($withdraw_log_data);
                DB::commit();
                ret(1, '打款成功，请等待申请人确认收款！');
            }else{
                throw new Exception('操作失败', 30001);
            }
        }catch (Exception $e){
            DB::rollback();
            ret(0, ($e->getCode() === 30001)?$e->getMessage():'店铺提现申请不存在');
        } finally {
            unset($id);
        }
    }

    #[申请人确认收到提现资金]
    public function finishedAction()
    {
        if (!$this->isPost()){
            ret(0, '请求出错');
        }
        $id = $this->get('id');
        DB::beginTransaction();
        try {
            $apply = dianpuwithdrawModel::query()->where('member_id', $this->user->id)->where('id', $id)->lockForUpdate()->firstOrFail();
            if ($apply->status < 2){
                throw new Exception('店铺掌柜未打款，不能确认收款', 30001);
            }
            if ($apply->status === 3){
                throw new Exception('已经确认过收款，无法重复确认', 30001);
            }
            $apply->status = 3;
            $apply->updated_at = timestamp();
            if($apply->save()){
                dianpuModel::moneyWithdrawFreeze($apply->money, $apply->dianpu_id, 'dianpuwithdrawfinished');
                $withdraw_log_data = [
                    'event'=>'finished',
                    'event_id'=>$apply->id,
                    'remark'=>"{$this->user->nickname}确认收到掌柜{$apply->dianpu_manager_id}的提现资金",
                    'oper_type'=>'user',
                    'oper_id'=>$this->user->id,
                    'created_at'=>timestamp(),
                ];
                dianpuwithdrawlogModel::query()->insert($withdraw_log_data);
                memberModel::money($apply->actual_money, $apply->dianpu_manager_id, 'dianpuwithdrawfinished', $apply->id, "用户{$apply->member_id}确认收到掌柜{$apply->dianpu_manager_id}的打款资金，增加{$apply->actual_money}元");
                DB::commit();
                ret(1, '确认收款成功！');
            }else{
                throw new Exception('操作失败', 30001);
            }
        }catch (Exception $e){
            DB::rollback();
            ret(0, ($e->getCode() === 30001)?$e->getMessage():'店铺提现申请不存在');
        } finally {
            unset($id);
        }
    }
}